import json
import math
import random
import string
import time
from hashlib import md5

import pytest
from Crypto.Cipher import AES, PKCS1_v1_5
from Crypto.PublicKey import RSA
from httpx import Client

http_client = Client(verify=False, base_url="https://openapi.kugou.com")

config_map = {
	"wx_appid": "wx79f2c4418704b4f8",
	"wx_lite_appid": "wx72b795aca60ad321",
	"wx_secret": "4efcab88b700769e376e3f6087b8abc9",
	"wx_lite_secret": "33e486041e5e25729a4e3d2da7502f9a",
	"srcappid": 2919,
	"appid": 1005,
	"apiver": 20,
	"clientver": 12569,
	"liteAppid": 3116,
	"liteClientver": 11040,
}

public_lite_rsa_key = """-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDECi0Np2UR87scwrvTr72L6oO01rBbbBPriSDFPxr3Z5syug0O24QyQO8bg27+0+4kBzTBTBOZ/WWU0WryL1JSXRTXLgFVxtzIY41Pe7lPOgsfTCn5kZcvKhYKJesKnnJDNr5/abvTGf+rHG3YRwsCHcQ08/q6ifSioBszvb3QiwIDAQAB\n-----END PUBLIC KEY-----"""

liteKey = "c24f74ca2820225badc01946dba4fdf7"
liteIv = "adc01946dba4fdf7"


# 填充函数，确保数据长度是 16 的倍数
def pad(data):
	padding_len = 16 - len(data) % 16
	return data + chr(padding_len) * padding_len


# 去除填充
def unpad(data):
	return data[: -ord(data[-1])]


# 加密函数
def encrypt_aes256cbc(plaintext: str, key: str = "", iv: str = ""):
	temp_key = ""
	if len(key) != 32 or len(iv) != 16:
		temp_key = "".join(random.sample(string.ascii_lowercase + string.digits, 16))
		key = md5_str(temp_key)
		iv = key[16:]

	cipher = AES.new(key.encode("utf-8"), AES.MODE_CBC, iv.encode("utf-8"))
	padded_data = pad(plaintext)
	print(f"{padded_data=}")
	ciphertext = cipher.encrypt(padded_data.encode("utf-8"))
	return ciphertext.hex(), temp_key


def md5_str(s: str):
	md5_obj = md5()
	md5_obj.update(s.encode("utf-8"))
	return md5_obj.hexdigest()


def crypto_rsa_encrypt(data: str):
	text = data.encode("utf-8")
	if len(text) < 128:
		text = text.ljust(128, b'\0')
	# elif len(text) > 128:
	# 	raise ValueError("Data too large for RSA key size")
	cipher_public = PKCS1_v1_5.new(RSA.importKey(public_lite_rsa_key))
	text_encrypted = cipher_public.encrypt(text)
	return text_encrypted.hex()


def signature_android_params(params: dict, data: str):
	key = "LnT6xpN3khm36zse0QzvmgTZ3waWdRSA"
	# sorted(params.items(), key=lambda item: item[0])
	sorted_dict = {k: params[k] for k in sorted(params)}
	params_string = "".join(f"{key}={value}" for key, value in sorted_dict.items())
	print(f"{params_string=}")
	temp = f"{key}{params_string}{data or ''}{key}"
	print(f"{temp=}")
	return md5_str(temp)


def sign_key(hash: str, mid: str, userid: int, appid: int):
	key = "57ae12eb6890223e355ccfcb74edf70d"
	return md5_str(f"{hash}{key}{appid}{mid}{userid or 0}")


def api(url: str, method: str, *, data: dict = None, params: dict = None, cookie: dict = None, headers: dict = None,
		encrypt_key: bool = False):
	if not data:
		data = {}
	if not params:
		params = {}
	if not cookie:
		cookie = {}
	if not headers:
		headers = {}

	client_time = int(time.time())
	# client_time = 1763789262
	df_id = cookie.get("dfid", "-")
	mid = md5_str(df_id)
	uuid = md5_str(f"{df_id}{mid}")
	token = cookie.get("token", "")
	userid = cookie.get("userid", 0)

	header_params = {
		"dfid": df_id,
		"mid": mid,
		"User-Agent": "Android15-1070-11083-46-0-DiscoveryDRADProtocol-wifi",
		# "x-router": "openapi.kugou.com",
		"clienttime": str(client_time),
		"X-Real-IP": "127.0.0.1",
		"X-Forwarded-For": "127.0.0.1",
	}
	header_params = header_params | headers
	print(f"{header_params=}")

	defaultParams = {
		"dfid": df_id,
		"mid": mid,
		"uuid": uuid,
		"appid": config_map["liteAppid"],
		"clientver": config_map["liteClientver"],
		"userid": userid,
		"clienttime": client_time,
	}
	if token:
		defaultParams.update({"token": token})

	request_params = {} | defaultParams | params
	if encrypt_key:
		request_params["key"] = sign_key(request_params.get("hash", ""), request_params["mid"],
										 request_params["userid"], request_params["appid"])

	request_data_str = json.dumps(data, separators=(",", ":")) if data else ""
	print(f"{request_data_str=}")
	request_params["signature"] = signature_android_params(request_params, request_data_str)
	print(f"{json.dumps(request_params, ensure_ascii=False)=}")
	try:
		# response = http_client.request(method=method, url=url, params=request_params, headers=header_params)
		response = http_client.request(method=method, url=url, params=request_params, content=request_data_str,
									   headers=header_params)
		if response.is_success:
			print(f"content = {json.dumps(response.json(), ensure_ascii=False, indent=2)}")

		else:
			print(f"{response.status_code=}")
			print(f"{response.text=}")
	except Exception as e:
		print(e)


# @pytest.mark.demo
# def test_get_all_list():
# 	cookie = {"token": "e61c7e211b3d9abcd3a4989f76dcb29ccdeef304d93a26dc3b37c653476e6763", "userid": "2181028551"}
# 	api("https://gateway.kugou.com/user/vip/detail", "POST", params={"plat": 1}, cookie=cookie,
# 		headers={"x-router": "cloudlist.service.kugou.com"},
# 		data={
# 			"total_ver": 979,
# 			"type": 2,
# 			"page": 1,
# 			"pagesize": "100"
# 		})

@pytest.mark.demo
def test_get_list():
	cookie = {"token": "e61c7e211b3d9abcd3a4989f76dcb29ccdeef304d93a26dc3b37c653476e6763", "userid": "2181028551"}
	client_time = int(time.time())
	p = crypto_rsa_encrypt(
		json.dumps({"client_time": client_time, "token": cookie["token"]}, separators=(",", ":"))).upper()
	api("https://listenservice.kugou.com/v2/get_list", "POST", data={
		"t_userid": '2181028551',
		"userid": '2181028551',
		"list_type": '1',
		"area_code": 1,
		"cover": 2,
		"p": p
	}, cookie=cookie, params={"plat": 0})


@pytest.mark.demo
def test_receive_vip_listen_song():
	cookie = {"token": "e61c7e211b3d9abcd3a4989f76dcb29ccdeef304d93a26dc3b37c653476e6763", "userid": "2181028551"}
	api("https://gateway.kugou.com/youth/v1/recharge/receive_vip_listen_song", "POST", params={
		"source_id": 90137
	}, cookie=cookie)


@pytest.mark.demo
def test_vip_detail():
	cookie = {"token": "e61c7e211b3d9abcd3a4989f76dcb29ccdeef304d93a26dc3b37c653476e6763", "userid": "2181028551"}
	api("https://kugouvip.kugou.com/v1/get_union_vip", "GET", params={
		"busi_type": 'concept',
	}, cookie=cookie)


@pytest.mark.demo
def test_api_audio():
	cookie = {"token": "4f7a1b1a9d8348065bf19d8e61d12181d5c03f4162db3c12705cff931e917b0c", "userid": "2181028551"}
	params = {"data": '[{"hash":"E214304168107D94921901E6117A8CDA"}]'}
	api("https://expendablekmrcdn.kugou.com/v1/audio_climax/audio", "GET", params=params, cookie=cookie)


@pytest.mark.demo
def test_api_url():
	cookie = {"token": "e61c7e211b3d9abcd3a4989f76dcb29ccdeef304d93a26dc3b37c653476e6763", "userid": "2181028551"}
	headers = {"x-router": "tracker.kugou.com"}

	api("https://gateway.kugou.com/v5/url", "GET", params={
		"album_audio_id": 0,
		"area_code": 1,
		"hash": "4E294957A0D9B72A78B61F3C2A63B6CC",
		# "vipType": "0",
		# "vipToken": "0",
		"behavior": "play",
		"version": "11709",
		# 是否返回试听部分（仅部分歌曲）
		"IsFreePart": "0",
		"album_id": "0",
		"ssa_flag": "is_fromtrack",
		"quality": "128",
		"pid": "2",
		"cmd": "26",
		"pidversion": "3001",
		"page_id": "967177915",
		"ppage_id": "356753938,823673182,967485191",
		"cdnBackup": "1",
		"kcard": "0",
		"module": "",
	}, cookie=cookie, headers=headers, encrypt_key=True)


@pytest.mark.demo
def test_api_search():
	cookie = {"token": "4f7a1b1a9d8348065bf19d8e61d12181d5c03f4162db3c12705cff931e917b0c", "userid": "2181028551"}
	headers = {"x-router": "complexsearch.kugou.com"}
	api(
		"https://gateway.kugou.com/v3/search/song",
		"GET",
		params={"keyword": "我可以", "category": 1, "page": "1", "pagesize": "10", "platform": "AndroidFilter"},
		cookie=cookie,
		headers=headers,
	)


@pytest.mark.demo
def test_api_author():
	cookie = {"token": "4f7a1b1a9d8348065bf19d8e61d12181d5c03f4162db3c12705cff931e917b0c", "userid": "2181028551"}
	headers = {"x-router": "openapi.kugou.com", "kg-tid": "36"}
	api("/kmr/v3/author", "POST", data={"author_id": "432"}, params={}, cookie=cookie, headers=headers)


@pytest.mark.demo
def test_url():
	# headers: {'x-router': 'openapi.kugou.com', 'KG-TID': '78'},
	print("url_test")

	# httpx.post("https://openapi.kugou.com/v2/search/song", json={"keyword": "周杰伦", "page": 1, "pagesize": 10}, headers={"x-router": "openapi.kugou.com", "KG-TID": "78"})
	#  获取毫秒值
	millis = int(round(time.time() * 1000))
	second = math.floor(millis / 1000)
	print(f"{second=}, {millis=}")
	encrypt_str, _ = encrypt_aes256cbc(liteKey, liteIv, json.dumps({"clienttime": second, "token": ""}))
	print(f"{encrypt_str=}")

	# temp_key = "".join(random.sample(string.ascii_lowercase + string.digits, 16))
	# md5_key = md5_str(temp_key)
	# print(f"{temp_key=}, {md5_key=}")

	encrypt_params, temp_key = encrypt_aes256cbc("{}")
	pk = crypto_rsa_encrypt(json.dumps({"clienttime_ms": millis, "key": temp_key}))

	dataMap = {
		"p3": "1",
		"plat": 1,
		"t1": 0,
		"t2": 0,
		"t3": "MCwwLDAsMCwwLDAsMCwwLDA=",
		"pk": pk,
		"params": "",
		"userid": "userid",
		"clienttime_ms": millis,
	}
	print(dataMap)
